package com.epoint.juc.single;

public class LazyMan {

    private volatile static LazyMan lazyMan = null;
    private static boolean flag = false;

    private LazyMan(){
        synchronized (LazyMan.class){
            if(!flag){
                flag = true;
            }else{
                throw new RuntimeException("禁止使用反射new对象");
            }
        }
    }

    public static LazyMan getInstance(){
        /**
         *  双if，为啥不把synchronized直接放在最外面，这样 就不需要写第二个if
         *  考虑到效率，绝大部分的线程可能都会被第一个if堵住了。少量的进去
         */
        if(lazyMan == null){
            synchronized (LazyMan.class){
                if(lazyMan == null){
                    /**
                     * 还有一个情况
                     *
                     * 因为 new LazyMan(); 不是一个原子性操作，他其实是分为3个步骤
                     * 1. 分配内存空间
                     * 2、执行构造方法，初始化对象
                     * 3、把这个对象指向这个空间
                     *
                     * 123
                     * 132 A
                     * B // 此时lazyMan还没有完成构造
                     * 故需要成员变量需要用volatile来修饰，阻止指令重排
                     */
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }
}
